<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
		<link rel="stylesheet" type="text/css" href="./static/jquery-easyui-1.8.1/themes/gray/easyui.css">
		<link rel="stylesheet" type="text/css" href="./static/jquery-easyui-1.8.1/themes/icon.css">
		<script type="text/javascript" src="./static/jquery-easyui-1.8.1/jquery.min.js"></script>
		<script type="text/javascript" src="./static/jquery-easyui-1.8.1/jquery.easyui.min.js"></script>
		<link rel="stylesheet" href="./static/zTree_v3.5.40/css/zTreeStyle/zTreeStyle.css" type="text/css">
		<link rel="stylesheet" href="./static/images/ztreeIconSkin.css" />
		<script type="text/javascript" src="./static/zTree_v3.5.40/js/jquery.ztree.all.js"></script>
		<script type="text/javascript" src="./static/js/jquery.cookie.js"></script>
		<script type="text/javascript" src="./static/js/ztreeData.js"></script>
		<script type="text/javascript" src="./static/js/jquery.xml2json.js"></script>
		<script>
			mxBasePath = './static/mxGraph';
		</script>
		<script type="text/javascript" src="./static/mxGraph/mxClient.js"></script>
		<!-- Example code -->
		<script type="text/javascript">
			// Program starts here. Creates a sample graph in the
			// DOM node with the specified ID. This function is invoked
			// from the onLoad event handler of the document (see below).
			var graph;
			var parent;

			function main(container) {
				// Checks if the browser is supported
				if (!mxClient.isBrowserSupported()) {
					mxUtils.error('Browser is not supported!', 200, false);
				} else {
					// Creates the graph inside the given container
					graph = new mxGraph(container);

					// 开启拖拽选择
					new mxRubberband(graph);

					//流程图自动布局
					//new mxCompactTreeLayout(graph);
					
					// Gets the default parent for inserting new cells. This
					// is normally the first child of the root (ie. layer 0).
					parent = graph.getDefaultParent();
					var currentPermission = null;
					var apply = function(permission) {
						graph.clearSelection();
						permission.apply(graph);
						graph.setEnabled(true);

						// Updates the icons on the shapes - rarely
						// needed and very slow for large graphs
						graph.refresh();
						currentPermission = permission;
					};
					//locked, createEdges, editEdges, editVertices, cloneCells
					apply(new Permission(false, false, false, true, false));


					// Extends hook functions to use permission object. This could
					// be done by assigning the respective switches (eg.
					// setMovable), but this approach is more flexible, doesn't
					// override any existing behaviour or settings, and allows for
					// dynamic conditions to be used in the functions. See the
					// specification for more functions to extend (eg.
					// isSelectable).
					var oldDisconnectable = graph.isCellDisconnectable;
					graph.isCellDisconnectable = function(cell, terminal, source) {
						return oldDisconnectable.apply(this, arguments) &&
							currentPermission.editEdges;
					};

					var oldTerminalPointMovable = graph.isTerminalPointMovable;
					graph.isTerminalPointMovable = function(cell) {
						return oldTerminalPointMovable.apply(this, arguments) &&
							currentPermission.editEdges;
					};

					var oldBendable = graph.isCellBendable;
					graph.isCellBendable = function(cell) {
						return oldBendable.apply(this, arguments) &&
							currentPermission.editEdges;
					};

					var oldLabelMovable = graph.isLabelMovable;
					graph.isLabelMovable = function(cell) {
						return oldLabelMovable.apply(this, arguments) &&
							currentPermission.editEdges;
					};

					var oldMovable = graph.isCellMovable;
					graph.isCellMovable = function(cell) {
						return oldMovable.apply(this, arguments) &&
							currentPermission.editVertices;
					};

					var oldResizable = graph.isCellResizable;
					graph.isCellResizable = function(cell) {
						return oldResizable.apply(this, arguments) &&
							currentPermission.editVertices;
					};

					var oldEditable = graph.isCellEditable;
					graph.isCellEditable = function(cell) {
						return oldEditable.apply(this, arguments) &&
							(this.getModel().isVertex(cell) &&
								currentPermission.editVertices) ||
							(this.getModel().isEdge(cell) &&
								currentPermission.editEdges);
					};

					var oldDeletable = graph.isCellDeletable;
					graph.isCellDeletable = function(cell) {
						return oldDeletable.apply(this, arguments) &&
							(this.getModel().isVertex(cell) &&
								currentPermission.editVertices) ||
							(this.getModel().isEdge(cell) &&
								currentPermission.editEdges);
					};

					var oldCloneable = graph.isCellCloneable;
					graph.isCellCloneable = function(cell) {
						return oldCloneable.apply(this, arguments) &&
							currentPermission.cloneCells;
					};

				}
			};

			function Permission(locked, createEdges, editEdges, editVertices, cloneCells) {
				this.locked = (locked != null) ? locked : false;
				this.createEdges = (createEdges != null) ? createEdges : true;
				this.editEdges = (editEdges != null) ? editEdges : true;;
				this.editVertices = (editVertices != null) ? editVertices : true;;
				this.cloneCells = (cloneCells != null) ? cloneCells : true;;
			};

			Permission.prototype.apply = function(graph) {
				graph.setConnectable(this.createEdges);
				graph.setCellsLocked(this.locked);
			}
			$(function() {
				main(document.getElementById('graphContainer'));
				setTimeout(initXmlData, 100);
				// initXmlData();
			})

			function initXmlData() {
				var xmlData = $.cookie('mxGraph-xml-withPorts');
				var node = mxUtils.parseXml(xmlData);
				
				/**
				 * 脑仁疼，使用这种加载方式后居然不能再操作文档了
				 * 更新啥的也没有任何异常提示
				 */
				// decoder = new mxCodec(node.ownerDocument);
				// decoder.decode(node, graph.getModel());
				var json_obj = $.xml2json(node);
				var mxCells = json_obj.root.mxCell;
				if (mxCells.length > 2) {
					graph.getModel().beginUpdate();
					try {
						for (var i = 2; i < mxCells.length; i++) {
							
							var isLine = mxCells[i]["@edge"];
							if (!isLine) {
								var id = mxCells[i]["@id"];
								var value = mxCells[i]["@value"];

								var posX = mxCells[i].mxGeometry["@x"];
								var posY = mxCells[i].mxGeometry["@y"];
								var width = mxCells[i].mxGeometry["@width"];
								var height = mxCells[i].mxGeometry["@height"];
								var styleCls = mxCells[i]["@style"];
								if(styleCls){
									var style = [];
									style[mxConstants.STYLE_SHAPE] = mxConstants.SHAPE_RECTANGLE;
									style[mxConstants.STYLE_PERIMETER] = mxPerimeter.RectanglePerimeter;
									style[mxConstants.STYLE_STROKECOLOR] = 'gray';
									style[mxConstants.STYLE_ROUNDED] = true;
									style[mxConstants.STYLE_FILLCOLOR] = '#EEEEEE';
									style[mxConstants.STYLE_GRADIENTCOLOR] = 'white';
									style[mxConstants.STYLE_FONTCOLOR] = '#774400';
									style[mxConstants.STYLE_ALIGN] = mxConstants.ALIGN_CENTER;
									style[mxConstants.STYLE_VERTICAL_ALIGN] = mxConstants.ALIGN_MIDDLE;
									style[mxConstants.STYLE_FONTSIZE] = '12';
									style[mxConstants.STYLE_FONTSTYLE] = 1;
									graph.getStylesheet().putCellStyle('exchanger', style);
									var cell = graph.insertVertex(parent, id, value, posX, posY, width, height);
									cell.setStyle(styleCls);
								}else{
									var cell = graph.insertVertex(parent, id, value, posX, posY, width, height);
								}
								
								
							}

						}

						for (var i = 2; i < mxCells.length; i++) {
							var isLine = mxCells[i]["@edge"];
							var id = mxCells[i]["@id"];
							var value = mxCells[i]["@value"];
							if (isLine && isLine == "1") {
								//说明是线
								var source = mxCells[i]["@source"];
								var target = mxCells[i]["@target"];
								var sourceCell = graph.getModel().getCell(source);
								var targetCell = graph.getModel().getCell(target);

								var line = graph.insertEdge(parent, id, value, sourceCell, targetCell, "");
								//纠正数据,如果没有起始或终止的话,那就把它干掉
								if (line.source == null || line.target == null) {
									line.removeFromParent();
									graph.refresh(line);
								}

							}

						}
					} finally {
						// Updates the display
						graph.getModel().endUpdate();
					}
				}


			}
		</script>
		<SCRIPT type="text/javascript">
			<!--
			var setting = {
				edit: {
					enable: true,
					showRemoveBtn: false,
					showRenameBtn: false
				},
				data: {
					simpleData: {
						enable: true
					}
				},
				callback: {
					beforeDrag: beforeDrag,
					beforeDrop: beforeDrop,
					onDrop: initEquipmentToTheGraph,
					onDblClick: initLineToTheGraph
				}
			};

			function initLineToTheGraph(event, treeId, treeNode) {
				//alert(treeNode ? treeNode.tId + ", " + treeNode.name : "isRoot");
				graph.getModel().beginUpdate();
				try {
					if (treeNode.iconSkin == "line") {
						var cells = graph.getSelectionCells();
						if (cells.length != 2) {
							$.messager.show({
								title: '温馨提示',
								msg: '请选择两个要连接的设备',
								showType: 'slide'
							});
						} else {
							var line = graph.insertEdge(parent, treeNode.id, treeNode.name, cells[0], cells[1], "");
							//TODO 这里其实还需要在树里删除线缆,因为线缆不能重复用的.
						}
					}

				} catch (e) {

				} finally {
					// Updates the display
					graph.getModel().endUpdate();
				}
			};




			function beforeDrag(treeId, treeNodes) {
				for (var i = 0, l = treeNodes.length; i < l; i++) {
					if (treeNodes[i].iconSkin == 'line') {
						$.messager.show({
							title: '温馨提示',
							msg: '线缆请勿拖拽，选择起始及终止设备后双击线缆即可',
							showType: 'slide'
						});
						return false;
					}
				}
				return true;
			}

			function initEquipmentToTheGraph(event, treeId, treeNodes, targetNode, moveType) {


				//将设备与线缆放置画布
				graph.getModel().beginUpdate();

				try {
					for (var i = 0; i < treeNodes.length; i++) {
						if (treeNodes[i].iconSkin == "server") {
							var v1 = graph.insertVertex(parent, treeNodes[i].id, treeNodes[i].name, event.clientX - 200, event.clientY -
								110,
								100, 30);

						} else if (treeNodes[i].iconSkin == "exchanger") {
							var style = [];
							style[mxConstants.STYLE_SHAPE] = mxConstants.SHAPE_RECTANGLE;
							style[mxConstants.STYLE_PERIMETER] = mxPerimeter.RectanglePerimeter;
							style[mxConstants.STYLE_STROKECOLOR] = 'gray';
							style[mxConstants.STYLE_ROUNDED] = true;
							style[mxConstants.STYLE_FILLCOLOR] = '#EEEEEE';
							style[mxConstants.STYLE_GRADIENTCOLOR] = 'white';
							style[mxConstants.STYLE_FONTCOLOR] = '#774400';
							style[mxConstants.STYLE_ALIGN] = mxConstants.ALIGN_CENTER;
							style[mxConstants.STYLE_VERTICAL_ALIGN] = mxConstants.ALIGN_MIDDLE;
							style[mxConstants.STYLE_FONTSIZE] = '12';
							style[mxConstants.STYLE_FONTSTYLE] = 1;
							graph.getStylesheet().putCellStyle('exchanger', style);
							var cell = graph.insertVertex(parent, treeNodes[i].id, treeNodes[i].name, event.clientX - 200, event.clientY -
								110,
								110, 40);
							cell.setStyle("exchanger");
						} else if (treeNodes[i].iconSkin == "line") {
							//不能创建没有起始终止点的线？
							// var tempStart = graph.insertVertex(parent, null, "", event.clientX - 200, event.clientY - 110, 10, 10);
							// var tempEnd = graph.insertVertex(parent, null, "", event.clientX - 100, event.clientY - 110, 10, 10);
							// graph.insertEdge(parent,treeNodes[i].id, treeNodes[i].name,tempStart,tempEnd,"");
							/**
							 * 不能曲线救国了，不管是隐藏还是移除对应线都没了
							 * 改为双击事件
							 */
							//tempStart.setVisible(false);
							// tempStart.removeFromParent();
							// tempEnd.removeFromParent();
							// graph.refresh(cell);
						}

					}

				} finally {
					// Updates the display
					graph.getModel().endUpdate();
				}
			};

			function beforeDrop(treeId, treeNodes, targetNode, moveType) {
				if (treeId) {
					return false;
				}
				return targetNode ? targetNode.drop !== false : true;
			}

			$(document).ready(function() {
				$.fn.zTree.init($("#treeDemo"), setting, zNodes);
			});
			//-->
			function saveGraph() {
				var enc1 = new mxCodec(mxUtils.createXmlDocument());
				var node1 = enc1.encode(graph.getModel());
				var xml1 = mxUtils.getXml(node1);
				$.cookie('mxGraph-xml-withPorts', xml1, {
					expires: 7
				});
				// $.messager.show({
				// 	title: '温馨提示',
				// 	msg: '数据保存成功！',
				// 	showType: 'slide'
				// });
			}

			function saveGraphAndAlert() {
				var enc1 = new mxCodec(mxUtils.createXmlDocument());
				var node1 = enc1.encode(graph.getModel());
				var xml1 = mxUtils.getXml(node1);
				$.cookie('mxGraph-xml-withPorts', xml1, {
					expires: 7
				});
				$.messager.show({
					title: '温馨提示',
					msg: '数据保存成功！',
					showType: 'slide'
				});
			}

			function exportGraph() {
				var enc1 = new mxCodec(mxUtils.createXmlDocument());
				var node1 = enc1.encode(graph.getModel());
				var xml1 = mxUtils.getXml(node1);
				$("#resultXML").html(xml1);
				$('#w').window('open');
			}

			function clearAllAndRrfreshPage() {
				$.messager.confirm('温馨提示', '您确定要清空重置网络拓扑图吗？', function(r) {
					if (r) {
						$.cookie('mxGraph-xml-withPorts', null);
						location.reload();
					}
				});
			}

			function deleteCellOrLine() {
				var cells = graph.getSelectionCells();
				if (cells.length == 0) {
					$.messager.alert('温馨提示', '请选择要删除的设备或线缆！', 'info');
				} else if (cells.length > 1) {
					$.messager.alert('温馨提示', '请选择一个进行删除操作！', 'info');
				} else {
					if (cells[0].edge) {
						//说明是线缆
						//如果啥都没有绑定的情况下可以删除

						//执行删除操作并保存
						graph.getModel().beginUpdate();
						try {
							cells[0].removeFromParent();
						} finally {
							graph.getModel().endUpdate();
						}
						saveGraph();
						graph.refresh(cells[0]);
					} else {
						if (cells[0].edges && cells[0].edges.length > 0) {
							$.messager.alert('温馨提示', '请先解绑线缆再删除！', 'info');
						} else {
							//执行删除操作并保存
							graph.getModel().beginUpdate();
							try {
								cells[0].removeFromParent();
							} finally {
								graph.getModel().endUpdate();
							}
							saveGraph();
							graph.refresh(cells[0]);
						}
					}

				}

			}

			function zoomInGraph() {
				graph.zoomIn();
			}

			function zoomOutGraph() {
				graph.zoomOut();
			}

			function zoomActualGraph() {
				graph.zoomActual();
			}
		</SCRIPT>
	</head>
	<body class="easyui-layout">
		<div data-options="region:'north'" style="height:50px;background:#f1f1f1;">
			<div style="font-size:18px;font-weight: bolder;padding:10px;">
				mxGraph在线绘制网络拓扑结构图Demo2
				<div style="float:right;">
					<a target="_blank" class="easyui-linkbutton" href="https://gitee.com/caolj/mxGraph-demo">源代码</a>
				</div>
			</div>

		</div>
		<div data-options="region:'east',split:true" title="East" style="width:200px;"></div>
		<div data-options="region:'west',split:true" title="配置区" style="width:200px;">
			<ul id="treeDemo" class="ztree"></ul>
		</div>
		<div data-options="region:'center',title:'网络拓扑图'">
			<div class="easyui-layout" data-options="fit:true,border:false">
				<div data-options="region:'north',border:false" style="height:40px;padding:5px;background: #f1f1f1;overflow: hidden;border-bottom:1px solid #ddd;">
					<a href="javascript:saveGraphAndAlert();" class="easyui-linkbutton" data-options="plain:true,iconCls:'icon-save'">保存</a>
					<a href="javascript:deleteCellOrLine();" class="easyui-linkbutton" data-options="plain:true,iconCls:'icon-remove'">删除</a>
					<a href="javascript:exportGraph();" class="easyui-linkbutton" data-options="plain:true,iconCls:'icon-print'">导出</a>

					<a href="javascript:zoomInGraph();" class="easyui-linkbutton" data-options="plain:true,iconCls:'icon-zoom_in'">放大</a>
					<a href="javascript:zoomOutGraph();" class="easyui-linkbutton" data-options="plain:true,iconCls:'icon-zoom_out'">缩小</a>
					<a href="javascript:zoomActualGraph();" class="easyui-linkbutton" data-options="plain:true,iconCls:'icon-zoom'">实际大小</a>
					<div style="float:right">
						<a href="javascript:clearAllAndRrfreshPage();" class="easyui-linkbutton" data-options="plain:true,iconCls:'icon-clear'">一键清空</a>
					</div>
				</div>
				<div data-options="region:'center',border:false">
					<!-- Creates a container for the graph with a grid wallpaper -->
					<div id="graphContainer" style="overflow:auto;width:100%;height:100%;background:url('./static/mxGraph/images/grid.gif')">
					</div>
				</div>
			</div>

		</div>
		<div id="w" class="easyui-window" title="导出XML结果" data-options="modal:true,closed:true" style="width:600px;height:400px;overflow: hidden;">
			<textarea id="resultXML" style="width:100%;height:100%;border:0px solid #fff;"></textarea>
		</div>
	</body>
</html>
